#!/usr/bin/env python
#coding=utf-8

import re
import os
import time
import logging

from common import config_data, log_info, log_exception,  get_symbol

from xsl import XLSWriter
from vic.exchange.vic_huobi.huobi_http import HuobiHttp
#from huobi_http import HuobiHttp

class HuobiService(HuobiHttp):
    """HuobiService"""
    def __init__(self, url, apikey, apisecret):
        super(HuobiHttp, self).__init__(url, apikey, apisecret)
        self.url       = url
        self.apiKey    = apikey
        self.apiSecret = apisecret
        self.http      = HuobiHttp(url, apikey, apisecret)

    def accounts(self):
        """火币账户信息"""
        account_info = self.http.accounts()
        return account_info


    def data(self):
        """火币账户信息"""

        account_info = self.accounts()
        _data = self.accounts()['data']
        return _data


    def accounts_data_list(self):
        """币安余额信息列表"""
        accounts  = self.accounts()
        data = accounts['data']
        data_list = []
        for d in data:
            balance_data = self.http.balance(d['id'])['data']['list']
            data_list.append(balance_data)
        return data_list


    def currency_list(self):
        """币种列表"""

        coin_list = []
        data = self.data()
        for d in data:
            accounts_data_list = self.http.balance(d['id'])['data']['list']
            for ad in accounts_data_list:
                balance  = float(ad['balance'])
                currency = ad['currency'].upper()
                if balance <= 0:
                    continue # 如果币种的余额等于0的就循环下一个

                coin_list.append(currency)
        return coin_list


    def balance(self):
        """余额"""
        balance = 0
        data = self.data()
        for d in data:
            accounts_data_list = self.http.balance(d['id'])['data']['list']
            for ad in accounts_data_list:
                balance += float(ad['balance'])
        return balance


    def tousdt_rate(self, currency):
        """火币转usdt比率"""

        currency = currency.lower()
        if currency == 'usdt':
            rate = 1
            return rate
        else:
            symbol = currency+'usdt'
            rate = self.http.detail_merged(symbol)['tick']['ask'][0]

        return rate


    def sum_usdt(self):
        """火币所有币种转usdt的总数"""

        sum  = 0
        data = self.data()
        for d in data:
            accounts_data_list = self.http.balance(d['id'])['data']['list']
            for ad in accounts_data_list:
                currency = ad['currency']
                balance  = float(ad['balance'])

                if balance != 0:
                    tousdt_rate = self.tousdt_rate(currency)
                    time.sleep(0.2)
                    sum += float(tousdt_rate*balance)
        return sum

    def currency_tousdt(self, currency):
        """币种转usdt的值"""
        usdt, currency = 0, currency.lower()
        data = self.data()
        for d in data:
            accounts_data_list = self.http.balance(d['id'])['data']['list']
            for ad in accounts_data_list:
                if currency == ad['currency']:
                    balance = float(ad['balance'])
                    tousdt_rate = self.tousdt_rate(currency)
                    usdt = float(tousdt_rate*balance)
                    break

        return usdt

    def conf_currency_tousdt_list(self):
        """获取配置文件币种转usdt的列表"""
        currency_tousdt_list = []
        file = "../conf/huobi-market-channels.txt"
        with open(file, 'r') as f:
            data      = f.read()
            data      = data.replace('\r', '')
            data_list = data.split('\n')
            for d in data_list:
                d_list = re.split(r'[\-\,]+', d)
                if not d_list[0] or d_list[0] != 'HUOBI' or d_list[2] != 'USDT':
                    continue # 不是BINA开头和USDT结尾的就循环下一个
                currency_tousdt_list.append(d_list[1])
        return currency_tousdt_list


    def huobi_cancel_order(self, currency, to_currency, start_date=None, end_date=None, _from=None, direct=None, size=1000000):
        """火币撤单"""

        symbol = get_symbol(currency, to_currency, 'huobi')
        states = 'pre-submitted,submitted,partial-filled,partial-canceled'
        self.orders(symbol, states=states, start_date=start_date, end_date=end_date, _from=_from, direct=direct, size=size)
        json = self.json
        if not json:
            log_info(u'火币撤销订单失败')
            return False

        order_id_list = [int(id.get('id')) for id in json['data'] if json and json.get('data')]
        order_id_list = map(lambda id:'%s' % id, list(set(order_id_list)))

        if len(order_id_list) <= 0:
            log_info(u'火币%s, 近期没有可撤消的订单'% symbol)
            return False

        order_ids   = {'order-id':order_id_list}
        order_num   = len(order_id_list)
        cancel_time = int(order_num/50) if order_num > 50 else 1 # 由于一次不能撤单超过50个，所以要分次数撤销
        calcel_num  = 0

        for ct in range(cancel_time):
            #log_info(u'### calcel_num:%s, order_ids:%s'% (calcel_num, order_ids))
            begin     = calcel_num*50
            end       = (calcel_num+1)*50

            order_ids = {'order-ids':order_id_list[begin:end]}
            self.http.cancel_orders(order_ids)
            json_data = self.http.json['data']
            if json_data:
                success   = json_data.get('success')
                log_info(u'火币撤单成功的订单id有:%s' % success)
            else:
                log_info(u'火币无单可撤')

            time.sleep(1)
            calcel_num += 1

        return True


    def huobi_cancel_allorder(self, currency=''):
        """火币撤销所有能撤销的订单"""

        # 账户id列表
        accounts_data = self.data()
        accounts_id_list = [a.get('id') for a in accounts_data]
        for id in accounts_id_list:
            balance      = self.http.balance(id)
            balance_list = balance['data']['list']
            for b in balance_list:
                currency = b.get('currency')
                balance  = float(b.get('balance'))
                type     = b.get('type')

                if currency and b.get('currency') != currency:
                    continue # 过滤不是要撤销的币种

                if currency == 'usdt' or balance <= 0:
                    continue # 如果是usdt或者余额不大于0的就循环下一个

                symbol = get_symbol(currency, 'usdt', 'huobi')
                if type == 'frozen':
                    self.huobi_cancel_order(currency, 'usdt')

        return True


    def symbol_order(self, uid, symbol, quantity, type='sell-market', user_type=''):
        """symbol下单"""
        price  = self.symbol_latest_price(symbol)
        source = 'margin-api' if user_type == 'margin' else 'api'
        self.http.place_order(uid, symbol, quantity, price, type, source)
        log_info(u'%s  下单价格:%s, 下单量:%s, 成功!'% (symbol, price, quantity))
        log_info(u'### json:%s'% self.http.json)
        return True

    def symbol_latest_price(self, symbol):
        """symbol最新价格"""
        kline = self.kline(symbol, '1min', 1)
        kline_low  = kline['data'][0]['low']
        return kline_low

    def account_order(self, uid, quantity, type, currency='', multiple=''):
        """账户下单"""
        tousdt_list = self.conf_currency_tousdt_list()
        if currency:
            symbol = get_symbol(currency, 'usdt', 'huobi')
            if symbol in tousdt_list:
                self.symbol_order(uid, symbol, quantity, type)
        else:
            accounts = self.accounts()
            user_data = accounts['data']
            data_list = [self.http.balance(data['id'])['data'] for data in user_data]
            uid_list  = [self.http.balance(data['id'])['data'].get('id') for data in user_data]
            for data in data_list:
                user_type    = data.get('type')
                state        = data.get('state')
                uid          = data.get('id')
                balance_list = data['list']

                for b in balance_list:
                    asset = b.get('currency')
                    balance  = float(b.get('balance'))
                    quantity = balance*float(multiple)
                    to_balance = balance - quantity
                    symbol = get_symbol(asset, 'usdt', 'huobi')

                    if asset == 'usdt' or asset.upper() not in tousdt_list:
                        continue

                    if currency and asset not in (currency.upper(), currency.lower()):
                        continue

                    if quantity <= 0.0004:
                        continue

                    self.symbol_order(uid, symbol, '%.3f'% float(quantity),
                                     type, user_type)
                    log_info(u'%s:递归下单开始'% symbol)
                    self.accounts_recursion(uid,
                                            currency,
                                            to_balance,
                                            balance_list,
                                            type,
                                            user_type)
                    log_info(u'%s:递归下单结束'% symbol)
        return True


    def accounts_recursion(self, uid, currency, to_balance, balance_list, type, user_type):
        """账户递归"""
        time.sleep(3) # 休息3秒再递归
        self.huobi_cancel_allorder(currency)
        for b in balance_list:
            asset = b.get('currency')
            if asset != currency:
                continue

            balance    = float(b.get('balance'))
            diff_price = balance - to_balance
            if diff_price > 0.01:
                symbol = get_symbol(asset, 'usdt', 'huobi')
                self.symbol_order(uid, symbol, '%.3f'% diff_price,
                                  type, user_type)
                return self.accounts_recursion(uid, currency,
                          to_balance, balance_list, type, user_type)
            return True



if __name__ == "__main__":

    url        = "https://api.huobipro.com"
    apiKey     = "8d22783f-7cb9e4c6-40ccd735-fa087"
    apiSecret  = "76b99517-fa66c3f7-eb9282d8-01c48"

    hs = HuobiService(url, apiKey, apiSecret)

    sum_usdt = hs.sum_usdt()
